package com.yeyks.commonReference.service.mattress.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.yeyks.account.dal.domain.AccountInfo;
import com.yeyks.account.utils.AccountUtil;
import com.yeyks.common.base.PageResult;
import com.yeyks.common.em.accountinfo.AccountInfoTypeEnum;
import com.yeyks.common.em.mattress.OrderInfoMattressEnum;
import com.yeyks.common.em.mattress.OrderInfoMattressStatusEnum;
import com.yeyks.common.em.pay.PayTypeEnum;
import com.yeyks.common.exception.ServiceException;
import com.yeyks.common.param.OrderInfoMattressParam;
import com.yeyks.common.result.OrderInfoMattressResult;
import com.yeyks.common.utils.DateUtils;
import com.yeyks.common.utils.IdWorkerUtil;
import com.yeyks.common.utils.ObjectConvertUtil;
import com.yeyks.commonReference.append.mattress.wechat.param.MattressWechatPayServiceRefundParam;
import com.yeyks.commonReference.append.mattress.wechat.service.MattressPayService;
import com.yeyks.commonReference.service.hotel.HotelInfoService;
import com.yeyks.commonReference.service.mattress.MattressApiService;
import com.yeyks.commonReference.service.mattress.MattressInfoService;
import com.yeyks.commonReference.service.mattress.OrderInfoMattressService;
import com.yeyks.hotel.dal.domain.HotelInfo;
import com.yeyks.mattress.dal.dao.OrderInfoMattressMapper;
import com.yeyks.mattress.dal.domain.MattressInfo;
import com.yeyks.mattress.dal.domain.MattressPackageConfig;
import com.yeyks.mattress.dal.domain.OrderInfoMattress;
import com.yeyks.mattress.param.CheckMattressStartSuccessParam;
import com.yeyks.mattress.param.OrderInfoMattressOrderListParam;
import com.yeyks.mattress.param.OrderInfoMattressOrderPayFailParam;
import com.yeyks.mattress.param.OrderInfoMattressPlaceAnOrderParam;
import com.yeyks.mattress.service.MattressPackageConfigService;
import com.yeyks.mattress.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 共享床垫订单表 服务实现类
 * </p>
 *
 * @author yun
 * @since 2019-07-16
 */
@Service
@Slf4j
public class OrderInfoMattressServiceImpl extends ServiceImpl<OrderInfoMattressMapper, OrderInfoMattress> implements OrderInfoMattressService {

    @Autowired
    private MattressInfoService mattressInfoService;
    @Autowired
    private HotelInfoService hotelInfoService;
    @Autowired
    private MattressPackageConfigService mattressPackageConfigService;
    @Autowired(required = false)
    private MattressApiService mattressApiService;
    @Autowired(required = false)
    private MattressPayService mattressPayService;

    @Override
    public OrderInfoMattressOrderListVo orderList(@Validated OrderInfoMattressOrderListParam param) {
        PageHelper.startPage(param.getPageNum(), param.getPageSize());
        List<OrderInfoMattress> list = list(new QueryWrapper<OrderInfoMattress>()
                .eq(OrderInfoMattress.USER_ID, param.getUserId())
                .orderByDesc(OrderInfoMattress.CREATE_TIME));
        PageInfo<OrderInfoMattress> orderInfoMattressPageInfo = new PageInfo<>(list);
        return new OrderInfoMattressOrderListVo().setPageInfo(orderInfoMattressPageInfo);
    }

    @Override
    public OrderInfoMattressPlaceAnOrderVo placeAnOrder(OrderInfoMattressPlaceAnOrderParam param) {
        //获取床垫信息
        MattressInfo mattressInfo = mattressInfoService.getOne(new QueryWrapper<MattressInfo>()
                .eq(MattressInfo.IMEI_ID, param.getImeiId())
                .eq(MattressInfo.STATUS, 1));
        if (null == mattressInfo) {
            throw new ServiceException("床垫不存在");
        }
        //获取床垫状态
        //v1.0.1
        OrderInfoMattressMattressStatusVo orderInfoMattressMattressStatusVo = mattressApiService.mattressStatusOnCheck(param.getImeiId());
        if (!Objects.equals(orderInfoMattressMattressStatusVo.getStatus(), 0)) {
            throw new ServiceException("床垫正在运行");
        }
        OrderInfoMattress orderInfoMattress = new OrderInfoMattress();
        orderInfoMattress.setOrderNo(IdWorkerUtil.nextStrId());
        orderInfoMattress.setUserId(param.getUserId());
        orderInfoMattress.setUserPhone(param.getUserPhone());
        orderInfoMattress.setHotelId(mattressInfo.getHotelId());
        orderInfoMattress.setImeiId(mattressInfo.getImeiId());
        //获取套餐信息
        MattressPackageConfig mattressPackageConfig = mattressPackageConfigService.getById(param.getPackageId());
        if (null == mattressPackageConfig) {
            throw new ServiceException("套餐不存在");
        }
        //获取酒店信息
        HotelInfo hotelInfo = hotelInfoService.getById(mattressInfo.getHotelId());
        if (null != hotelInfo) {
            orderInfoMattress.setHotelName(hotelInfo.getName());
            orderInfoMattress.setHotelPhone(hotelInfo.getPhone());
            orderInfoMattress.setHotelFeeValue(mattressPackageConfig.getSalePrice() * hotelInfo.getMattressPercent() / 100);
            orderInfoMattress.setProvinceAgentId(hotelInfo.getProvinceAgentId());
            orderInfoMattress.setCityAgentId(hotelInfo.getCityAgentId());
            orderInfoMattress.setHotelAddress(hotelInfo.getAddress());
        }
        orderInfoMattress.setPackageId(mattressPackageConfig.getId());
        orderInfoMattress.setPackageName(mattressPackageConfig.getPackageName());
        orderInfoMattress.setPackageContent(mattressPackageConfig.getPackageContent());
        orderInfoMattress.setPackageTimeLong(mattressPackageConfig.getTimeLong());
        orderInfoMattress.setSnapshotTotalFee(mattressPackageConfig.getSalePrice());
        orderInfoMattress.setStatus(OrderInfoMattressStatusEnum.PRE_PAY.value());
        orderInfoMattress.setCalculateFlag(0);
        Date nowData = new Date();
        orderInfoMattress.setCreateTime(nowData);
        orderInfoMattress.setModifyTime(nowData);
        boolean b = save(orderInfoMattress);
        if (!b) {
            throw new ServiceException("订单创建失败");
        }
        return new OrderInfoMattressPlaceAnOrderVo().setOrderNo(orderInfoMattress.getOrderNo());
    }

    @Override
    public OrderInfoMattressOrderPayFailVo orderPayFail(OrderInfoMattressOrderPayFailParam param) {
        //查询
        OrderInfoMattress orderInfoMattress = getOne(new QueryWrapper<OrderInfoMattress>()
                .eq(OrderInfoMattress.ORDER_NO, param.getOrderNo()).eq(OrderInfoMattress.USER_ID, param.getUserId())
                .eq(OrderInfoMattress.STATUS, OrderInfoMattressStatusEnum.PRE_PAY.value()));
        if (null == orderInfoMattress) {
            throw new ServiceException("订单不存在");
        }
        //修改
        OrderInfoMattress orderInfoMattressNew = new OrderInfoMattress().setId(orderInfoMattress.getId()).setStatus(OrderInfoMattressStatusEnum.PAYMENT_FAILED.value());
        boolean b = updateById(orderInfoMattressNew);
        return new OrderInfoMattressOrderPayFailVo().setSuccess(b);
    }

    /**
     * 订单列表
     *
     * @param param
     * @return
     */
    @Override
    public PageResult<OrderInfoMattressResult> myList(OrderInfoMattressParam param, AccountInfo loginUser) {
        QueryWrapper<OrderInfoMattress> wrapper = new QueryWrapper<>();
        if (null != param.getArea()) {
            wrapper.like(OrderInfoMattress.HOTEL_ADDRESS, param.getArea());
        }
        if (null != param.getStartTime() && null == param.getEndTime()) {
            wrapper.ge(OrderInfoMattress.CREATE_TIME, DateUtils.stampToYMDHMSDate(param.getStartTime()));
        }
        if (null != param.getEndTime() && null == param.getStartTime()) {
            wrapper.le(OrderInfoMattress.CREATE_TIME, DateUtils.stampToYMDHMSDate(param.getEndTime()));
        }
        if (null != param.getEndTime() && null != param.getStartTime()) {
            Date startDate = DateUtils.stampToYMDHMSDate(param.getStartTime());
            Date endDate = DateUtils.stampToYMDHMSDate(param.getEndTime());
            wrapper.between(OrderInfoMattress.CREATE_TIME, startDate, endDate);
        }
        if (null != param.getHotelName()) {
            wrapper.like(OrderInfoMattress.HOTEL_NAME, param.getHotelName());
        }
        if (null != param.getOrderNo()) {
            wrapper.eq(OrderInfoMattress.ORDER_NO, param.getOrderNo());
        }
        if (AccountInfoTypeEnum.HotelManager.value().equals(loginUser.getType())) {
            HotelInfo hotelInfo = hotelInfoService.searchHotelByOperator(AccountUtil.getOperationUserId(loginUser));
            wrapper.eq(OrderInfoMattress.HOTEL_ID, hotelInfo.getId());
        }
        wrapper.orderByDesc(OrderInfoMattress.CREATE_TIME);
        PageHelper.startPage(param.getPageNum(), param.getPageSize());
        List<OrderInfoMattress> orderInfoMattresses = baseMapper.selectList(wrapper);
        PageInfo<OrderInfoMattress> of = PageInfo.of(orderInfoMattresses);
        return new PageResult<>(of.getTotal(), of.getPageSize(), of.isHasNextPage(), of.getNextPage(), getOrderInfoMattress(orderInfoMattresses));
    }

    /**
     * 共享床垫退款
     *
     * @param orderNo   订单号
     * @param loginUser 当前操作人
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean refund(String orderNo, AccountInfo loginUser) {
        OrderInfoMattress orderInfoMattress = baseMapper.selectOne(new QueryWrapper<OrderInfoMattress>().eq(OrderInfoMattress.ORDER_NO, orderNo));
        if (null == orderInfoMattress) {
            throw new ServiceException("该共享床垫订单不存在");
        }
        if (!OrderInfoMattressEnum.Status.STARTUP_FAILED.value().equals(orderInfoMattress.getStatus())) {
            throw new ServiceException("非启动失败状态不能退款");
        }
        //订单退款
        MattressWechatPayServiceRefundParam refundParam = new MattressWechatPayServiceRefundParam();
        refundParam.setOrderNo(orderInfoMattress.getOrderNo());
        refundParam.setRefundFee(orderInfoMattress.getSnapshotTotalFee());
        refundParam.setTotalFee(orderInfoMattress.getSnapshotTotalFee());
        refundParam.setPayType(PayTypeEnum.getDesc(orderInfoMattress.getPaymentMethod()));
        if (mattressPayService.disPoseRefund(refundParam)) {
            orderInfoMattress.setStatus(OrderInfoMattressEnum.Status.REFUND_SUCCESS.value());
            orderInfoMattress.setModifyTime(new Date());
            if (1 != baseMapper.updateById(orderInfoMattress)) {
                log.info("修改床垫订单状态为退款成功失败orderNo = {}", orderNo);
            }
            return true;
        } else {
            return false;
        }
    }

    /**
     * 共享床垫订单转换
     *
     * @param orderInfoMattresses
     * @return
     */
    private List<OrderInfoMattressResult> getOrderInfoMattress(List<OrderInfoMattress> orderInfoMattresses) {
        List<OrderInfoMattressResult> results = Lists.newArrayList();
        for (OrderInfoMattress orderInfoMattress : orderInfoMattresses) {
            OrderInfoMattressResult result = ObjectConvertUtil.convertObject(orderInfoMattress, OrderInfoMattressResult.class);
            if (null == result) {
                continue;
            }
            result.setCreateTime(DateUtils.formatYMDHMSStr(orderInfoMattress.getCreateTime()));
            result.setStatus(OrderInfoMattressEnum.Status.getDesc(orderInfoMattress.getStatus()));
            results.add(result);
        }
        return results;
    }

    @Override
    public CheckMattressStartSuccessVo checkMattressStartSuccess(CheckMattressStartSuccessParam param) {
        OrderInfoMattress orderInfoMattress = getOne(new QueryWrapper<OrderInfoMattress>()
                .eq(OrderInfoMattress.ORDER_NO, param.getOrderNo())
                .last("limit 1")
        );
        if (Objects.isNull(orderInfoMattress)) {
            throw new ServiceException("订单不存在");
        }
        if (Objects.equals(orderInfoMattress.getStatus(), OrderInfoMattressStatusEnum.STARTUP_SUCCESSFUL.value())) {
            return new CheckMattressStartSuccessVo().setSuccess(true);
        }
        return new CheckMattressStartSuccessVo().setSuccess(false);
    }

}
